from server import db, app
from sqlalchemy import Column, String
from itsdangerous import BadSignature, SignatureExpired
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from werkzeug.security import generate_password_hash, check_password_hash
from sqlalchemy.dialects.mysql import TINYINT
from server.model import BaseOrm


# 系统用户
class SysUser(BaseOrm):
    __tablename__ = 'sys_user'
    username = Column(String(64), nullable=False, server_default='', comment="用户名 ")
    password = Column(String(255), nullable=False, server_default='', comment="密码 ")
    name = Column(String(64), nullable=False, server_default='', comment="姓名(昵称) ")
    mobile = Column(String(32), nullable=False, server_default='', comment="手机号 ")
    status = Column(TINYINT(4), nullable=False, server_default='0', comment="状态 0:禁用，1:正常 ")
    remark = Column(String(64), nullable=False, server_default='', comment="备注 ")
    is_modify_pwd = Column(TINYINT(4), nullable=False, server_default='0', comment="是否修改过初始密码 ")

    def generate_auth_token(self, expiration=60 * 60 * 20):
        s = Serializer(app.config['SECRET_KEY'], expires_in=expiration)
        return s.dumps({'id': self.id})

    @staticmethod
    def verify_auth_token(token):
        s = Serializer(app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
        except SignatureExpired:
            return None  # valid token, but expired
        except BadSignature:
            return None  # invalid token
        admin = SysUser.query.get(data['id'])
        if not admin:
            return None
        return admin

    def get_roles(self):
        from .sys_user_role import SysUserRole
        from .role import Role
        role_ids = SysUserRole.query.filter(SysUserRole.user_id == self.id).all()
        role_ids = {u.role_id for u in role_ids}
        roles = Role.query.filter(Role.id.in_(role_ids)).all()
        return roles

    def is_admin(self):
        roles = self.get_roles()
        for role in roles:
            if role.name == "sys" or role.name == "manager":
                return True
        return False

    def set_psw(self, password):
        self.password = generate_password_hash(password)

    def check_psw(self, password):
        return check_password_hash(self.password, password)

    def to_dict(self, include=None, exclude=None):
        result = super().to_dict(include, exclude)
        result['roles'] = [u.id for u in self.get_roles()]
        return result

    @staticmethod
    def init_admin():
        from .route import Route
        from .role import Role
        from .role_route import RoleRoute
        from .sys_user_role import SysUserRole
        from server.model.sys import PERMISSION
        admin_role = Role.query.filter_by(name='sys').one_or_none()
        if not admin_role:
            admin_role = Role(name='sys')
            db.session.add(admin_role)
            db.session.commit()
        admin = SysUser.query.filter_by(username='sys').one_or_none()
        if admin:
            return
        admin = SysUser(username='sys')
        db.session.add(admin)
        admin.set_psw('123456')
        db.session.commit()

        db.session.add(SysUserRole(user_id=admin.id, role_id=admin_role.id))
        db.session.commit()

        RoleRoute.query.filter_by(role_id=admin_role.id).delete()
        all_routes = Route.query.all()
        for route in all_routes:
            role_route = RoleRoute(role_id=admin_role.id, route_id=route.id, permission=PERMISSION.CRUD)
            db.session.add(role_route)
        db.session.commit()


db.create_all()
# SysUser.init_admin()
